Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support 'oxford comma' format and non-string types in listing #690

Merged
merged 8 commits into from
Jan 17, 2025

Conversation

zwimer
Copy link
Contributor

@zwimer zwimer commented Sep 27, 2024

Fixes: #693

This PR:

  1. Adds support for the 'oxford comma' format list format in listing. Depending on location etc., some people list items using an oxford comma. For example:
x = []
for i in range(3):
    x.append(i)
    print(listing(z, ",", "and"))
    print(listing(z, ",", "and", oxford=True))

Prints out

0
0
0 and 1
0 and 1
0, 1 and 2
0, 1, and 2

The default is oxford=False to avoid changing the default behavior.

  1. Allows the use of types other than str in listing. The code for this function almost entirely already allowed this, this PR mostly changes type annotations and adds a couple of str() calls to fully support it. This allows for things like:
class Translate:
    def __init__(self, msg, language):
        self.msg = msg
        self.language = language
    def __str__(self) -> str:
        return translate(self.language, self.msg)   #  External API call 

print(listing([1, 2], ","))  # Non-string items
print(listing([1, 2], ",", Translator("and", "Spanish"))  # Non-string separators and conjunctions

Which may print:

1, 2
1 y 2
  1. Fixes type annotation on items. Python defines list type as invariant; we should use Sequence instead as that is covariant. That is:
class Special(str):
    pass

s = [Special("")]

x: list[str] = s       # type error: since list is invariant, list[Special] is not a list[str]
y: Sequence[str]  = s  # ok: since Sequence is covariant, list[DerivedClass] is a list[BaseClass]

@zwimer
Copy link
Contributor Author

zwimer commented Dec 30, 2024

@staticdev The test case for coverage for listing fail before because if TYPE_CHECKING: clauses never get executed during runtime; they are only executed by type checkers like mypy. To deal with this, I added a .coveragerc and instructed it to ignore lines guarded by this if statement.

from typing import TYPE_CHECKING


if TYPE_CHECKING:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess it is much simpler to just remove this if statement and always import this. It is the standard approach.

@@ -38,3 +38,22 @@ def test_listing_with_conjunction(
) -> None:
"""Listing with separator and conjunction."""
assert lists.listing(*params) == expected


@pytest.mark.parametrize(
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would also be great to explain this in our examples documentation.

@staticdev
Copy link
Owner

staticdev commented Jan 4, 2025

@staticdev The test case for coverage for listing fail before because if TYPE_CHECKING: clauses never get executed during runtime; they are only executed by type checkers like mypy. To deal with this, I added a .coveragerc and instructed it to ignore lines guarded by this if statement.

@zwimer I did a review, and I have a suggestion to deal with this in a simpler way.

@staticdev staticdev merged commit 47ef9ab into staticdev:main Jan 17, 2025
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Oxford comma support in listings
2 participants